
Imports std

Public Module common

    Public Function configDeletedOperation(Optional ByRef configfile As String = Nothing) As Boolean
        Return configMonitor.defaultConfigDeletedOperation(3600000, 32, configfile)
    End Function

    Public Class talkTime
        Public Class room2node
            Public Const holdtime As Int64 = tcpServer2.defaultHoldTime << 1
            Public Const livetime As Int64 = tcpServer2.defaultLiveTime << 4
            Public Const retrytimes As UInt64 = 3
        End Class

        Public Class client2room
            Public Const holdtime As Int64 = tcpServer2.defaultHoldTime << 2
            Public Const livetime As Int64 = holdtime
            Public Const retrytimes As UInt64 = 16
        End Class

        Public Class share
            Public Const minHealthHoldTime As Int64 = 500
            Public Const minHealthRetryTimes As UInt64 = 1
        End Class
    End Class

    Public Class connectionCount
        Public Const room As Int32 = 512
        Public Const node As Int32 = 128
    End Class

    Public Class threadCount
        'the latency is at network, so leave more threads to wait for network
        Public Const room As Int64 = 128
        'the latency is at disk, so more threads are useless in node
        Public Const node As Int64 = 32
    End Class
End Module

Namespace protocol

    Public Module protocol
        Public Const success As String = "suc"
        Public Const fail As String = "fal"
        Public Const unknown As String = "unk"
    End Module

    Namespace port
        Public Module port
            Public Const stornode As Int32 = 42331
            Public Const storoom As Int32 = 42332
        End Module
    End Namespace

    Namespace storserver
        Public Module storserver
            Public Const write As String = "wrt"
            Public Const uniqueWrite As String = "uwt"
            Public Const delete As String = "del"
            Public Const modify As String = "mod"
            Public Const read As String = "rad"
            Public Const seek As String = "sek"
            Public Const capacity As String = "cap"
            Public Const valuesize As String = "vsz"
            Public Const list As String = "lst"
            Public Const status As String = "sts"
            Public Const open As String = "opn"
            Public Const close As String = "cls"
            Public Const full As String = "ful"
            Public Const health As String = "hlt"
            Public Const retire As String = "rtr"
            Public Const empty As String = "emp"
            Public Const sizeof As String = "szf"
            Public Const keycount As String = "kct"
            Public Const sync As String = "syn"
            Public Const version As String = "ver"

            Public Const tsRead As String = "ts.rad"
            Public Const tsWrite As String = "ts.wrt"
            Public Const tsModify As String = "ts.mod"
            Public Const tsSeek As String = "ts.sek"
            Public Const tsList As String = "ts.lst"
            Public Const tsDelete As String = "ts.del"
            Public Const tsSizeof As String = "ts.szf"
            Public Const tsKeycount As String = "ts.kct"
        End Module
    End Namespace
End Namespace

Public Module _common
    Private Const timestampkeyPrefix As String = "t."
    Private Const datakeyPrefix As String = "d."

    Public Function timestampkey(ByVal key As String) As String
        Return timestampkeyPrefix + key
    End Function

    Public Function datakey(ByVal key As String) As String
        Return datakeyPrefix + key
    End Function

    Public Function istimestampkey(ByVal key As String) As Boolean
        Return strsame(key, timestampkeyPrefix, strlen(timestampkeyPrefix), True)
    End Function

    Public Function isdatakey(ByVal key As String) As Boolean
        Return strsame(key, datakeyPrefix, strlen(datakeyPrefix), True)
    End Function

    Public Function originalkey(ByVal key As String) As String
        Dim datakey As Boolean = False
        Dim timestampkey As Boolean = False
        datakey = isdatakey(key)
        timestampkey = istimestampkey(key)
        If debugassert(datakey OrElse timestampkey, "should only get originalkey with datakey or timestampkey.") Then
            If datakey Then
                Return strmid(key, strlen(datakeyPrefix))
            Else
                Return strmid(key, strlen(timestampkeyPrefix))
            End If
        Else
            Return Nothing
        End If
    End Function

    Public Sub normalizeTalk(ByRef talk As storoomTalk)
        If talk Is Nothing Then
            talk = storoom
        End If
    End Sub

    Public Const suffixSeparator As Char = character.dot

    Public Function generatekey(ByVal key As String, ByVal suffix As String) As String
        Return key + suffixSeparator + suffix
    End Function

    Public Function generatekey(ByVal key As String, ByVal index As Int64) As String
        Return generatekey(key, Convert.ToString(index))
    End Function
End Module

Public Class locks
    Private Shared ReadOnly lockbuff As bytes = Nothing
    Private Shared locked As [set](Of String) = Nothing

    Shared Sub New()
        lockbuff = New bytes(encoding.utf8.GetBytes("HH"))
        locked = New [set](Of String)()
    End Sub

    Public Shared Function lock(ByVal key As String, ByVal talk As storoomTalk) As Boolean
        'just save some network usage
        While locked.find(key) <> locked.end()
            sleep()
        End While

        If talk Is Nothing Then
            talk = storoom
        End If

        'if the server is not health or full, do not waste time
        If Not talk.health() OrElse talk.full() Then
            Return False
        End If

        While Not talk.uniqueWrite(lockkey(key), lockbuff)
            sleep()
        End While
        locked.insert(key)

        Return True
    End Function

    Public Shared Function release(ByVal key As String, ByVal talk As storoomTalk) As Boolean
        If locked.find(key) = locked.end() Then
            Return False
        Else
            If talk Is Nothing Then
                talk = storoom
            End If

            If talk.delete(lockkey(key)) Then
                Return locked.erase(key)
            Else
                Return False
            End If
        End If
    End Function

    Public Const lockKeySuffix As Char = character.numberMark

    Private Shared Function lockkey(ByVal key As String) As String
        Return generatekey(key, lockKeySuffix)
    End Function
End Class
